package role

import (
	"context"
	"fmt"
	"github.com/zeromicro/go-zero/core/fx"
	"go-admin/base/dao"
	"go-admin/base/utils"

	"go-admin/base/internal/svc"
	"go-admin/base/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type ListLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListLogic {
	return &ListLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *ListLogic) List(req *types.RoleQueryReqDTO) (resp *types.RoleRespDTOS, err error) {
	roles, err := l.svcCtx.RoleModel.FindAll(l.ctx)
	if err != nil {
		_ = fmt.Errorf(err.Error())
		return nil, err
	}
	roleIds := utils.Collector[int64](fx.From(func(source chan<- any) {
		for _, role := range roles {
			source <- role
		}
	}).Map(func(item any) any {
		role := item.(*dao.Role)
		return role.Id
	}))
	// 根据 roleIds 查询 权限
	rolePermissions, err := l.svcCtx.RolePermissionModel.FindRolePermissionsByRoleIds(l.ctx, roleIds)
	if err != nil {
		_ = fmt.Errorf(err.Error())
		return nil, err
	}
	permissionIds := utils.Collector[int64](fx.From(func(source chan<- any) {
		for _, rolePermission := range rolePermissions {
			source <- rolePermission
		}
	}).Map(func(item any) any {
		rolePermissionModel := item.(*dao.RolePermission)
		return rolePermissionModel.PermissionId
	}))
	//caller := utils.Caller[[]*dao.Permission](func() (any, error) {
	//	return l.svcCtx.PermissionModel.FindByPermissionIds(l.ctx, permissionIds)
	//})
	permissions, err := l.svcCtx.PermissionModel.FindByPermissionIds(l.ctx, permissionIds)
	if err != nil {
		_ = fmt.Errorf(err.Error())
		return nil, err
	}

	// 根据 roleIds 查询 用户
	userRoles, err := l.svcCtx.UserRoleModel.FindUserRolesByRoleIds(l.ctx, roleIds)
	if err != nil {
		_ = fmt.Errorf(err.Error())
		return nil, err
	}
	userIds := utils.Collector[int64](fx.From(func(source chan<- any) {
		for _, userRole := range userRoles {
			source <- userRole
		}
	}).Map(func(item any) any {
		userRole := item.(*dao.UserRole)
		return userRole.UserId
	}))
	users, err := l.svcCtx.UserModel.FindByUserIds(l.ctx, userIds)
	if err != nil {
		_ = fmt.Errorf(err.Error())
		return nil, err
	}

	var roleRespDTOs []types.RoleRespDTO

	for _, role := range roles {
		roleId := role.Id
		// 用户
		var userRespDTOs []types.UserRespDTO
		fx.From(func(source chan<- any) {
			for _, userRole := range userRoles {
				source <- userRole
			}
		}).Filter(func(item any) bool {
			userRole := item.(*dao.UserRole)
			return userRole.RoleId == roleId
		}).ForEach(func(item any) {
			userRole := item.(*dao.UserRole)
			userId := userRole.UserId
			userRoleId := userRole.Id
			first := fx.From(func(source chan<- any) {
				for _, user := range users {
					source <- user
				}
			}).Filter(func(item any) bool {
				user := item.(*dao.User)
				return user.Id == userId
			}).First()
			user := first.(*dao.User)
			userRespDTOs = append(userRespDTOs, types.UserRespDTO{
				UserID:     userId,
				UserNum:    user.UserNum.String,
				UserName:   user.UserName.String,
				NickName:   user.NickName.String,
				UserRoleID: userRoleId,
			})
		})

		// 权限
		var permissionRespDTOs []types.PermissionRespDTO

		fx.From(func(source chan<- any) {
			for _, rolePermission := range rolePermissions {
				source <- rolePermission
			}
		}).Filter(func(item any) bool {
			rolePermission := item.(*dao.RolePermission)
			return rolePermission.RoleId == roleId
		}).ForEach(func(item any) {
			rolePermission := item.(*dao.RolePermission)
			permissionId := rolePermission.PermissionId
			rolePermissionId := rolePermission.Id
			first := fx.From(func(source chan<- any) {
				for _, permission := range permissions {
					source <- permission
				}
			}).Filter(func(item any) bool {
				permission := item.(*dao.Permission)
				return permission.Id == permissionId
			}).First()
			permission := first.(*dao.Permission)

			permissionRespDTOs = append(permissionRespDTOs, types.PermissionRespDTO{
				PermissionID:     permissionId,
				ParentID:         permission.ParentId.Int64,
				URL:              permission.Url.String,
				Type:             permission.Type.String,
				Name:             permission.Name.String,
				Number:           permission.Number.String,
				RolePermissionID: rolePermissionId,
			})
		})

		roleRespDTOs = append(roleRespDTOs, types.RoleRespDTO{
			RoleID:      roleId,
			RoleName:    role.Name.String,
			Users:       userRespDTOs,
			Permissions: permissionRespDTOs,
		})

	}

	return &types.RoleRespDTOS{
		Data: roleRespDTOs,
		Result: types.Result{
			Code: 200,
		},
	}, nil
}
